package Thread;

/**
 * @className: BlockingQueue
 * @author: 芃
 * @description: 阻塞队列
 * @date: 2024/1/14 20:43
 */
class MyBlockingQueue{
    private int[] data = new int[1000];
    private volatile int size = 0;//有效元素个数
    private volatile int head = 0;//队首下标
    private volatile int tail = 0;//队尾下标
    private final Object locker = new Object();//专门的锁对象

    //入队列
    public void put(int val) throws InterruptedException {
        synchronized (locker){
            while(size == data.length){
                //阻塞条件,就是队列满了
                //队列满了,暂时先直接返回
                locker.wait();
            }
            //把新的元素放到tail下标
            data[tail] = val;
            tail++;
            size++;
            //如果入队列成功,则队列非空,于是就唤醒take中的阻塞等待
            locker.notify();
            //处理tail到达数组末尾的情况
            if(tail == data.length){
                tail = 0;
            }
        }
    }
    //出队列
    public Integer take() throws InterruptedException {
        synchronized (locker){
            while (size == 0){
                //队列为空,就返回一个非法值
                locker.wait();
            }
            //取出head下标的元素
            int ret = data[head];
            head++;
            //处理head走到数组末尾的情况
            if(head == data.length){
                head = 0;
            }
            size--;
            //take成功之后,就唤醒put中的等待
            locker.notify();
            return ret;
        }
    }
}
public class BlockingQueue {
    public static void main(String[] args) {
        MyBlockingQueue queue = new MyBlockingQueue();
        //生产者
        Thread t1 = new Thread(()->{
            int num = 1;
            while (true){
                try {
                    queue.put(num);
                    System.out.println("生产元素："+num);
                    Thread.sleep(500);
                    num++;
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        //消费者
        Thread t2 = new Thread(()->{
            while (true) {
                int ret = 0;
                try {
                    ret = queue.take();
                    System.out.println("消费元素："+ret);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t1.start();
        t2.start();
    }
}
